package qq2564874169.tuaotuao.fx.caching;

import qq2564874169.tuaotuao.fx.FxAssert;
import qq2564874169.tuaotuao.fx.FxStream;
import qq2564874169.tuaotuao.fx.utils.ClassUtil;
import qq2564874169.tuaotuao.fx.utils.JsonUtil;
import qq2564874169.tuaotuao.fx.utils.StringUtil;

import java.io.Serializable;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;

public abstract class RemoteCache implements Cache {
    private static String hexPrefix = "$HEX-";

    protected String serialize(Object value) {
        return JsonUtil.toJson(value);
    }

    protected final String valueSerialize(Object value) {
        if (value instanceof String) {
            return (String) value;
        }
        if (value instanceof Serializable) {
            String hex = ClassUtil.serialize(value);
            if (hex != null) {
                return hexPrefix + hex;
            }
        }
        return serialize(value);
    }

    protected final Object valueDeserialize(String value, Class<?> clazz) {
        if (StringUtil.isNullOrEmpty(value)) {
            return null;
        }
        if (clazz == String.class) {
            return value;
        }
        if (value.startsWith(hexPrefix)) {
            value = value.substring(hexPrefix.length());
            return ClassUtil.deserialize(value);
        }
        return deserialize(value, clazz);
    }

    protected Object deserialize(String value, Class<?> clazz) {
        if (value.startsWith("[")) {
            return JsonUtil.toList(value, clazz);
        }
        return JsonUtil.toObject(value, clazz);
    }

    protected abstract void saveRemote(RemoteCacheItem item);

    protected abstract RemoteCacheItem getRemoteItem(String key);

    protected abstract void deleteRemote(String key);

    protected abstract boolean existsRemote(String key);

    @Override
    public void save(CacheItem item) {
        FxAssert.isNotNull(item.value, "保存的值不能是空");
        var save = new RemoteCacheItem();
        Class<?> valueClass = item.value.getClass();
        if (valueClass.isArray()) {
            valueClass = item.value.getClass().getComponentType();
            save.isArray = true;
            item.value = valueSerialize(item.value);
        } else if (item.value instanceof List) {
            FxAssert.isFalse(((List<?>) item.value).isEmpty(), "不能保存元素为空的List");
            valueClass = ((List<?>) item.value).get(0).getClass();
            save.isList = true;
            item.value = valueSerialize(item.value);
        } else if (item.value instanceof Map) {
//            valueClass = Map.class;
//            isMap = true;
            throw new RuntimeException("不支持Map");
        }
        if (valueClass.getTypeName().contains("$")) {
            FxAssert.isTrue(Modifier.isStatic(valueClass.getModifiers()), "内部类必须是静态的:" + valueClass.getTypeName());
        }
        save.key = item.key;
        save.value = valueSerialize(item.value);
        save.valueClass = valueClass.getTypeName();
        save.absoluteExpiration = item.absoluteExpiration;
        save.slidingExpiration = item.slidingExpiration;
        saveRemote(save);
    }

    @Override
    public void remove(String key) {
        deleteRemote(key);
    }

    @Override
    public boolean exists(String key) {
        return existsRemote(key);
    }

    @Override
    public Object get(String key) {
        RemoteCacheItem data = getRemoteItem(key);
        if (data == null) {
            return null;
        }
        Class<?> clazz = ClassUtil.forName(data.valueClass);
        FxAssert.isNotNull(clazz, "无法加载的类型：" + data.valueClass);
        var rs = valueDeserialize(data.value, clazz);
        if (data.isArray && rs instanceof List<?>) {
            return FxStream.create((List) rs).toArray(clazz);
        }
        return rs;
    }
}
